package com.hlk.article.controller;

import com.hlk.article.service.ArticleService;
import com.hlk.article.utils.RestTemplateUtils;
import com.hlk.config.RabbitmqConfig;
import com.hlk.constant.Constant;
import com.hlk.controller.article.ArticleControllerApi;
import com.hlk.enums.ArticleCoverType;
import com.hlk.enums.ArticleReviewStatusEnum;
import com.hlk.enums.ResponseStatusEnum;
import com.hlk.enums.YesOrNo;
import com.hlk.exception.HuaException;
import com.hlk.feign.ArticleFeignClient;
import com.hlk.pojo.Category;
import com.hlk.pojo.bo.NewArticleBO;
import com.hlk.pojo.vo.ArticleDetailVO;
import com.hlk.result.Result;
import com.hlk.utils.JsonUtils;
import com.hlk.utils.PageResult;
import com.hlk.utils.ValidateUtils;
import com.hlk.utils.redis.RedisKeys;
import com.hlk.utils.redis.RedisUtils;
import com.mongodb.client.gridfs.GridFSBucket;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.validation.Valid;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author hlk
 * @version 1.0
 * @date 2020-12-30 15:02
 */
@RestController
public class ArticleController implements ArticleControllerApi {
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private ArticleService articleService;
    @Value("${freemarker.target.article}")
    private String targetPath;
    @Autowired
    private GridFSBucket gridFSBucket;
    @Autowired
    private RestTemplateUtils restTemplateUtils;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private ArticleFeignClient articleFeignClient;

    @Override
    public Result createArticle(@Valid NewArticleBO newArticleBO, BindingResult result) {
        // 校验参数是否符合
        if (result.hasErrors()) {
            Map<String, String> map = ValidateUtils.checkParams(result);
            return Result.errorMap(map);
        }

        // 判断文章封面类型，单图必填，纯文字则设置为空
        if (newArticleBO.getArticleType().equals(ArticleCoverType.ONE_IMAGE.type)) {
            if (StringUtils.isBlank(newArticleBO.getArticleCover())) {
                return Result.errorCustom(ResponseStatusEnum.ARTICLE_COVER_NOT_EXIST_ERROR);
            }
        } else if (newArticleBO.getArticleType().equals(ArticleCoverType.WORDS.type)) {
            newArticleBO.setArticleCover("");
        }

        // 判断分类是否存在
        String categoryStr = redisUtils.get(RedisKeys.getCategoryKey());
        boolean flag = true;
        if (StringUtils.isBlank(categoryStr)) {
            throw new HuaException(ResponseStatusEnum.SYSTEM_OPERATION_ERROR);
        } else {
            List<Category> list = JsonUtils.jsonToList(categoryStr, Category.class);
            for (Category category : list) {
                if (category.getId().equals(newArticleBO.getCategoryId())) {
                    flag = false;
                    break;
                }
            }
        }
        if (flag) {
            throw new HuaException(ResponseStatusEnum.ARTICLE_CATEGORY_NOT_EXIST_ERROR);
        }

        articleService.createArticle(newArticleBO);

        return Result.ok();
    }

    @Override
    public Result queryMyList(String userId, String keyword, Integer status, Date startDate, Date endDate, Integer page, Integer pageSize) {
        if (StringUtils.isBlank(userId)) {
            return Result.errorCustom(ResponseStatusEnum.ARTICLE_QUERY_PARAMS_ERROR);
        }

        if (page == null) {
            page = Constant.PAGE;
        }
        if (pageSize == null) {
            pageSize = Constant.PAGESIZE;
        }

        PageResult pageResult = articleService.selectMyList(userId, keyword, status, startDate, endDate, page, pageSize);
        return Result.ok(pageResult);
    }

    @Override
    public Result queryAllList(Integer status, Integer page, Integer pageSize) {
        if (page == null) {
            page = Constant.PAGE;
        }
        if (pageSize == null) {
            pageSize = Constant.PAGESIZE;
        }

        PageResult pageResult = articleService.selectAllList(status, page, pageSize);
        return Result.ok(pageResult);
    }

    @Override
    public Result doReview(String articleId, Integer passOrNot) {
        Integer pendingStatus;
        if (passOrNot.equals(YesOrNo.YES.type)) {
            // 审核成功
            pendingStatus = ArticleReviewStatusEnum.SUCCESS.type;

        } else if (passOrNot.equals(YesOrNo.NO.type)) {
            // 审核失败
            pendingStatus = ArticleReviewStatusEnum.FAILED.type;
        } else {
            return Result.errorCustom(ResponseStatusEnum.ARTICLE_REVIEW_ERROR);
        }

        // 保存到数据库，更改文章的状态为审核成功或者失败
        articleService.updateArticleStatus(articleId, pendingStatus);

        if (passOrNot.equals(YesOrNo.YES.type)) {
            // 审核通过，生成文章详情静态页面
            try {
                String articleMongoId = createArticleHtmlToGridFs(articleId);
                articleService.updateArticleToGridFS(articleId, articleMongoId);
                // 远程调用，下载静态文件
//                restTemplateUtils.downloadArticleHtml(articleId, articleMongoId);
                // 发消息到rabbitmq
                rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_ARTICLE, "article.html.download", articleId + "," + articleMongoId);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return Result.ok();
    }


    /**
     * 生成文章详情静态文件
     *
     * @param articleId
     * @throws Exception
     */
    public String createArticleHtmlToGridFs(String articleId) throws Exception {
        Configuration configuration = new Configuration(Configuration.getVersion());
        // 声明freemarker模板所需要加载的目录位置
        String classpath = this.getClass().getResource("/").getPath();
        configuration.setDirectoryForTemplateLoading(new File(classpath + "templates"));
        // 获取现有ftl模板
        Template template = configuration.getTemplate("detail.ftl", "utf-8");
        // 获得动态数据
//        ArticleDetailVO articleDetailVO = restTemplateUtils.getArticleDetail(articleId);
        Result bodyResult = articleFeignClient.detail(articleId);
        ArticleDetailVO articleDetailVO = null;
        if (bodyResult.getStatus() == 200) {
            String detailJson = JsonUtils.objectToJson(bodyResult.getData());
            articleDetailVO = JsonUtils.jsonToPojo(detailJson, ArticleDetailVO.class);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("articleDetail", articleDetailVO);

        String htmlContent = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);

        InputStream inputStream = IOUtils.toInputStream(htmlContent);
        ObjectId objectId = gridFSBucket.uploadFromStream(articleId + ".html", inputStream);
        return objectId.toString();
    }

    /**
     * 生成文章详情静态文件
     *
     * @param articleId
     * @throws Exception
     */
    public void createArticleHtml(String articleId) throws Exception {
        Configuration configuration = new Configuration(Configuration.getVersion());
        // 声明freemarker模板所需要加载的目录位置
        String classpath = this.getClass().getResource("/").getPath();
        configuration.setDirectoryForTemplateLoading(new File(classpath + "templates"));
        // 获取现有ftl模板
        Template template = configuration.getTemplate("detail.ftl", "utf-8");
        // 获得动态数据
//        ArticleDetailVO articleDetailVO = restTemplateUtils.getArticleDetail(articleId);
        Result result = articleFeignClient.detail(articleId);
        ArticleDetailVO articleDetailVO = null;
        if (result.getStatus() == 200) {
            String detailJson = JsonUtils.objectToJson(result.getData());
            articleDetailVO = JsonUtils.jsonToPojo(detailJson, ArticleDetailVO.class);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("articleDetail", articleDetailVO);

        // 融合动态数据和ftl生成html
        File file = new File(targetPath);
        if (!file.exists()) {
            file.mkdirs();
        }

        FileWriter out = new FileWriter(targetPath + File.separator + articleId + ".html");
        template.process(map, out);
        out.close();

    }


    @Override
    public Result delete(String userId, String articleId) {
        articleService.deleteArticle(userId, articleId);
//        restTemplateUtils.deleteArticleHtml(articleId);
        // 发消息到rabbitmq
        rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_ARTICLE, "article.html.delete", articleId);

        return Result.ok();
    }

    @Override
    public Result withdraw(String userId, String articleId) {
        articleService.withdrawArticle(userId, articleId);
//        restTemplateUtils.deleteArticleHtml(articleId);
        // 发消息到rabbitmq
        rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_ARTICLE, "article.html.delete", articleId);
        return Result.ok();
    }
}
